package net.sf.ivyide;

import fr.jayasoft.ivy.ModuleId;
import fr.jayasoft.ivy.ModuleRevisionId;

import java.io.File;
import java.util.*;

public class ModuleManager {
    private final Map<ModuleId, DependencyType> m_moduleDependencies;
    private ModuleProvider m_moduleProvider;
    private File m_rootModuleDir;
    private Map<ModuleId, File> m_modules;
    private Map<File, ModuleSourceDescriptor> m_cachedModuleDescriptors = new LinkedHashMap<File, ModuleSourceDescriptor>();

    public ModuleManager(ModuleProvider moduleProvider, Map<ModuleId, DependencyType> moduleDependencies, File rootModuleDir) {
        m_moduleDependencies = moduleDependencies;
        m_moduleProvider = moduleProvider;
        m_rootModuleDir = rootModuleDir;
    }

    public ModuleSourceDescriptor getModuleSource(File moduleDir) {
        ModuleSourceDescriptor descriptor = m_cachedModuleDescriptors.get(moduleDir);
        if (descriptor == null) {
            descriptor = m_moduleProvider.getModuleSource(moduleDir);
            m_cachedModuleDescriptors.put(moduleDir, descriptor);
        }
        return descriptor;
    }

    public Map<ModuleId, File> getModules() {
        if (m_modules == null) {
            m_modules = m_moduleProvider.getModules();
        }
        return m_modules;
    }

    public Map<ModuleId, DependencyType> getModuleDependencyTypes() {
        return m_moduleDependencies;
    }

    public ResolvedModule resolveModule(File moduleDir) {
        return m_moduleProvider.resolveModule(moduleDir);
    }

    public int getAmountOfSourceModules() {
        int count = 0;
        for (DependencyType dependencyType : m_moduleDependencies.values()) {
            if (DependencyType.SOURCE.equals(dependencyType)) {
                count++;
            }
        }
        return count;
    }

    public File getRootModuleDir() {
        return m_rootModuleDir;
    }

    public LibraryDescriptor getLibraryDescriptor(ResolvedModule module, ModuleRevisionId libraryRevisionId) {
        //   File moduleSourceDescriptor = modules.get(moduleRevisionId.getModuleId());
        LibraryDescriptor descriptor = module.getLibraryDescriptor(libraryRevisionId);
        File moduleSourceDescriptor = getModules().get(libraryRevisionId.getModuleId());
        if (moduleSourceDescriptor != null) {
            File[] sources = descriptor.getSources();
            if (sources.length == 0) {
                //If source is not added to ivy, fallback to source on disk..
                Set<File> sourceFiles = new LinkedHashSet<File>();
                ContentRoot[] contentRoots = getModuleSource(moduleSourceDescriptor).getContentRoots();
                for (ContentRoot contentRoot : contentRoots) {
                    sourceFiles.addAll(Arrays.asList(contentRoot.getMainJavaDirs()));
                    sourceFiles.addAll(Arrays.asList(contentRoot.getTestJavaDirs()));
                }
                sources = sourceFiles.toArray(new File[sourceFiles.size()]);
            }
            return new LibraryDescriptorImpl(descriptor.getClasses(), sources, descriptor.getJavadocs());
        } else {
            return descriptor;
        }
    }

    public Map<ModuleId, DependencyType> getDependantModules(ResolvedModule resolvedModule) {
        Collection<ModuleRevisionId> dependencies = resolvedModule.getDependencies();
        Map<ModuleId, DependencyType> dependantModules = new LinkedHashMap<ModuleId, DependencyType>();
        Map<ModuleId, File> modules = getModules();
        for (ModuleRevisionId moduleRevisionId : dependencies) {
            ModuleId moduleId = moduleRevisionId.getModuleId();
            File moduleSourceDescriptor = modules.get(moduleId);
            if (moduleSourceDescriptor != null) {
                DependencyType dependencyType = getModuleDependencyTypes().get(moduleId);
                if (dependencyType == null)
                    dependencyType = DependencyType.LIBRARY;
                dependantModules.put(moduleId, dependencyType);
            }
        }
        return dependantModules;

    }
}